home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
007
/
as02.arc
/
SCAV30.ASM
< prev
next >
Wrap
Assembly Source File
|
1985-08-28
|
14KB
|
553 lines
title scavenge Copyright (c) T. Jennings 1983
;
;****************************************
;* *
;* SCAVENGE *
;* *
;* Mark bad blocks on MSDOS *
;* as allocated in the FAT. *
;* *
;* T. Jennings 5 June 82 *
;* created 15 Sept. 82 *
;* Modified 14 December 1984 *
;* by David Gwillim *
;* *
;* *
;****************************************
;
;***********************************************************************
;** **
;** SCAV2XX was modified by David Gwillim to dynamically allocate **
;** memory to the variables BLKBUF and FATBUF when the program **
;** is started - this drastically reduced the size of the .COM file **
;** from 17K on disk to just over 1K, while still allowing the **
;** checking of disks with block sizes up to 16K Bytes. Also **
;** changed was the access to disk to determine its statistics **
;** (Number of Blocks, Blocksize etc) this is now done AFTER the **
;** pause command when the program is first started, permitting **
;** the program to be run with a single floppy drive. Code was **
;** also added to display the block size of the disk in bytes **
;** as part of the statistics, plus some alert tones for various **
;** parts of the program. **
;** **
;** I also added a more graceful exit than via ^C or Cntrl-Break **
;** as this would often leave you on the wrong drive if you aborted **
;** mid way through the block check and also would not give you the **
;** chance to update the FAT with any bad blocks found so far. **
;** **
;** A logical improvement to the program would be to add to the **
;** code so the program could report the names of the files which **
;** contain any bad blocks found, so the user could handle those **
;** files, or at least be aware that the data in them was corrupted. **
;** **
;** This is a very useful program and can give you great peace of **
;** mind if you own a hard disk and want to be sure that all is OK. **
;** If anyone takes a crack at doing the improvements I mentioned **
;** or finds and fixes any bugs, I would be delighted to hear of **
;** them. **
;** **
;** David Gwillim **
;** 1414 N. Catalina Street **
;** Los Angeles CA 90027 **
;** **
;************************************************************************
;
;Reads all sectors in logical MSDOS blocks
;and marks the file allocation tables such
;that the blocks are permanently allocated
;where CHKDSK will not deallocate them.
;
;
;This version works on any 2.xx MSDOS or
;PCDOS, on any media type, fixed or removable.
;One (major) limitation: it will not map out
;blocks that are already allocated to a file;
;it will say "block used", but won't tell you
;which file it is in.
;
;If SCAVENGE finds any bad blocks, it will ask
;you whether or not you want the disk updated.
;You can safely run it just to see if the disk
;is OK.
;
;MASM, LINK, then EXE2BIN this to make a COM
;file. It will not run as an EXE file. NOTE:
;LINK will give you a 'Warning: no STACK
;segment' error: ignore it.
;
cr equ 0dh
lf equ 0ah
;Beep procedure count values
;---------------------------
;To generate a given freqency note out of the speaker with the Beep procedure
;on the PC using Channel 2 of the 8253 timer, the channel 2 count register
;must be loaded with a value such that the 8253 input clock frequency
;(1.19318 MHz) divided by the count figure equals the audio frequency.
f176Hz equ 6779 ; 176 Hz count value
f352Hz equ 3390 ; 352 Hz count value
f704Hz equ 1695 ; 704 Hz count value
f1408Hz equ 847 ; 1408 Hz count value
page
cgroup group code
code segment byte public 'code'
assume cs:cgroup,ds:cgroup,ss:cgroup
;
;MSDOS page 0 stuff.
;
org 5ch
tfcb label byte
org 80h
tbuff label byte
org 100h
scavenge:
jmp start
;
;Disk parameters:
;
blkcnt dw (?) ;blocks this disk
blksize dw (?) ;sectors per block
secsize dw (?) ;phys. sector size
badcnt dw (?) ;# bad blocks found
newbad dw (?) ;new bad ones
block dw (?) ;current block
sector dw (?) ;sector to read
disk db (?) ;selected disk
curdsk db (?) ;current disk.
fatsec dw (?) ;1st FAT sector,
fatcnt dw (?) ;FAT sec count.
dw 128 dup (?)
stack dw (?) ;what else
page
;
;Say who we are, describe the disk we are
;about to fix, ask to continue or abort.
;
start: mov ax,cs
mov ds,ax
cli ;Disable interrupts while we move stack
mov ss,ax
mov sp,offset stack
sti ;Re-enable interrupts
mov dx,offset signon
call putstr
mov bx,f176Hz ;Alert user audibly
call beep
mov bx,f704Hz
call beep
mov bx,f352Hz
call beep
mov bx,f1408Hz
call beep
call ina
or al,20h ;Make character lower case
cmp al,'q' ;Quit?
jne st0
mov dx,offset abort
call putstr
int 20h
st0: call setup ;get disk stuff
jnc st1
call putstr
int 20h ;error.
st1: call liststat ;describe dsk
;
;Find all the bad blocks, if any, display them,
;ask if we should update the FAT. If so, write
;it out.
;
mov dx,offset crlf
call putstr
call findbad ;map bad,
call listbad ;list them,
cmp newbad,0 ;if new bad
je st2 ;blocks...
mov dx,offset updstr ;ask if we
call putstr ;should update
call ina
and al,5fh
cmp al,'Y'
jne st1A
mov al,disk ;write out the
mov dx,fatsec ;FAT,
mov cx,fatcnt
mov bx,offset fatbuf
int 26h
pop ax ;pop flags
mov dx,offset update
call putstr
jmp st2
st1A: mov dx,offset noupdte
call putstr
st2: mov al,curdsk ;reselect the
call seldsk ;original disk
int 20h
signon db cr,lf,9,'*********************************************'
db cr,lf,9,'* DOS 2.xx Bad Sector Mapper - Version 3.00 *'
db cr,lf,9,'* Updated by David Gwillim 18 December 1984 *'
db cr,lf,9,'* Original program by T. Jennings 5 June 83 *'
db cr,lf,9,'*********************************************'
db cr,lf,lf
db 'Type Q to abort at any time, any other key to continue ...'
db cr,lf,'$'
updstr db cr,lf,lf,'Want the disk updated? [y,n] $'
noupdte db cr,lf,lf,'FAT not updated',cr,lf,'$'
update db cr,lf,lf,'FAT updated',cr,lf,'$'
crlf db cr,lf,'$'
page
;
;Get the data on the specified disk. Return
;carry if no drive specified. Returns ES:DI
;pointing to the FAT for the selected drive.
;
setup: call initdsk ;reset dsk sys,
call getdsk ;get current,
mov curdsk,al ;save it,
mov al,tfcb ;make sure a
cmp al,0 ;new one spec'd
stc ;quit if none,
mov dx,offset strstr
jz gd1
dec al ;make 0-N,
mov disk,al
call seldsk ;select,
push ds ;save local DS,
mov ah,1bh
int 21h
pop ds
mov blkcnt,dx ;save # blocks,
mov secsize,cx ;sector size,
mov ah,0
mov blksize,ax ;secs/block.
push ds ;now get the
mov dl,disk
inc dl ;drive 1=A, b=2
mov ah,32h ;FAT,
int 21h ;get the DPB,
mov cx,[bx+15] ;CX= sec count,
mov ch,0
mov dx,[bx+6] ;DX= 1st sec,
pop ds
mov fatcnt,cx ;save both,
mov fatsec,dx
mov al,disk ;AL= drive #,
mov bx,offset fatbuf ;DS:BX= buffer
int 25h ;read the FAT,
pop ax ;pop flags
mov dx,offset bscstr
gd1: ret
strstr db cr,lf,'Must specify a disk drive.$'
bscstr db cr,lf,'Bad FAT sector: disk not useable.$'
page
;
;Read the entire disk looking for bad blocks.
;When one is found, go mark it as an allocated
;bad block.
;
findbad:
mov block,0 ;1st block,
mov badcnt,0 ;none yet,
fb1: call kbdchk ;QUIT character input from the keyboard?
jnc fb1A
mov dx,offset abort
call putstr
ret
fb1A: mov dx,offset blkstr ;type 'block '
call putstr
mov bx,block ;block number,
call outdec
call readblk ;read a block,
jnc fb3 ;if bad,
inc badcnt ;count it,
mov dx,offset badstr
call putstr ;type 'bad'
call mapout ;mark bad,
mov dx,offset cntstr ;error if cant
jc fb2
add newbad,cx ;count it,
mov dx,offset alrstr
jcxz fb2 ;already marked
mov dx,offset mrkstr
mov bx,f704Hz ;Warn user audibly
call beep
mov bx,f176Hz
call beep
fb2: call putstr
mov bx,f1408Hz ;Warn user audibly
call beep
mov bx,f176Hz
call beep
fb3: inc block ;next block,
dec blkcnt ;another...
jnz fb1 ;keep looking.
ret
blkstr db cr,'Block $'
badstr db ' bad,$'
alrstr db ' already marked.',cr,lf,'$'
mrkstr db ' mapped out.',lf,'$'
cntstr db ' already used! I dont know which file.',lf,'$'
abort db ' ... Aborting program',cr,lf,lf,'$'
page
;
;Mark the current block as bad in the FAT.
;Multiply the block number by 1.5 to find the
;block number, (actually *3, /2) and if not
;used, mark it bad. If used, report which file
;it's in. If it's already mapped as bad,
;return CX=0, else return CX=1.
;
mapout:
mov bx,block ;block,
shl bx,1 ;first times 2,
add bx,block ;then add one to make times 3,
shr bx,1 ;now divide by 2,
mov ax,word ptr fatbuf[bx] ;get word,
;
;If carry is set, we want the high 12 bits in
;the word in AX, else the low 12 bits. Set CH
;as the shift count, DX as the mask.
;
mov ch,0 ;assume low,
mov dx,0fffh
jnc mo1
mov ch,4 ;else high 12,
mov dx,0fff0h
mo1: and ax,dx ;mask it,
mov cl,ch
shr ax,cl ;shift it,
;
;AX is the block number; if it's anything
;but 000 or ff7, return with carry set,
;indicating that it's already used.
;
cmp ax,0ff7h ;if ff7,
je mo2 ;already marked
cmp ax,0 ;if allocated,
je mo3
stc ;error!
mo2: mov cx,0 ;none mapped,
ret
;
;Bad unused block. Mark as bad in the FAT.
;
mo3: mov ax,0ff7h ;marker,
mov cl,ch
shl ax,cl ;shift it,
or word ptr fatbuf[bx],ax ;mark it.
mov cx,1 ;1 mapped,
ret
page
;
;Read one block, return carry set if read
;error. Leave the useless data in the buffer
;following the end of this program.
;
readblk:
mov ax,block ;find start
mov cx,blksize ;sector,
mul cx ;CX= count,
mov dx,ax ;DX= sector,
mov al,disk
mov bx,offset blkbuf ;our buffer,
int 25h ;read sectors,
pop dx ;pop flags,
ret
page
;
;List the general info on the disk, like
;number of blocks, block size, FAT size & location, etc.
;
liststat:
mov dx,offset st1str
call putstr
mov al,disk
add al,'A'
call outa
mov dx,offset st2str
call putstr
mov bx,blkcnt
call outdec
mov dx,offset st3str
call putstr
mov ax,512
mul blksize
mov bx,ax
call outdec
mov dx,offset st4str
call putstr
mov bx,fatcnt
call outdec
mov dx,offset st5str
call putstr
mov bx,fatsec
call outdec
mov dx,offset st6str
call putstr
ret
;Disk A: Total of 12345 data blocks 1024 bytes each.
st1str db cr,lf,'Disk $'
st2str db ': Total of $'
st3str db ' data blocks $'
st4str db ' bytes each.',cr,lf,'$'
st5str db ' FAT sectors, first FAT sector is logical sector $'
st6str db cr,lf,'$'
;
;List out the bad things about this disk.
;
listbad:
mov dx,offset bd1str
call putstr
mov bx,badcnt
call outdec
mov dx,offset bd2str
call putstr
mov bx,newbad
call outdec
mov dx,offset bd3str
call putstr
ret
;Total of 12345 bad blocks, found 12234 more this pass.
bd1str db cr,'Total of $' ;note no linefeed.
bd2str db ' bad blocks, found $'
bd3str db ' more this pass.',cr,lf,'$'
page
;
;Generally useful system calls.
;
putstr: mov ah,9
int 21h
ret
;
;Type BX in decimal, suppressing leading
;zeros.
;
outdec: mov cl,0 ;0 suppress flag,
mov dx,10000
call rsdiv
mov dx,1000
call rsdiv
mov dx,100
call rsdiv
mov dx,10
call rsdiv
mov ch,bl
jmp odf
rsdiv: mov ch,-1 ;iteration -1,
rs1: inc ch ;count,
sub bx,dx ;subtract,
jnc rs1 ;til underflow,
add bx,dx ;adjust back,
cmp ch,0 ;if non-zero,
jne odf ;type it,
test cl,1 ;dont type 0's
jnz odf ;if leading,
ret
odf: push dx
mov dl,ch
add dl,'0' ;ASCII,
mov ah,2
int 21h
pop dx
mov cl,1 ;no suppress,
ret
page
;
;More system calls.
;
seldsk: mov dl,al ;select disk,
mov ah,0eh
int 21h
ret
getdsk: mov ah,19h
int 21h
ret
initdsk:mov ah,0dh
int 21h
ret
ina: mov ah,0ch ;char in with no echo
mov al,8 ;and flush.
int 21h
ret
kbdchk: mov ah,0Bh ;Check keyboard for character waiting
int 21h
cmp al,0
jz chk1
mov ah,8 ;Character waiting - see what it is
int 21h
or al,20h ;Make it lower case
cmp al,'q' ;Time to QUIT?
je chk2 ;Yes
chk1: clc ;No - Make sure carry flag is cleared
ret
chk2: stc ;Yep - set carry flag
ret
outa: mov dl,al
mov ah,2
int 21h
ret
;
; BEEP - entry conditions BX register contains count figure for frequency
; to be generated.
;
beep: mov al,0b6h ; Channel 2, LSB then MSB, Square Wave, Binary
out 43h,al ; Program 8253 command register
mov ax,bx ; Get the frequency to be generated
out 42h,al ; Load Channel 2 count register LSB
mov al,ah
out 42h,al ; Load Channel 2 count register MSB
in al,61h ; Read settings from 8255 PPI I/O Port "PB"
mov ah,al ; Save original settings in AH
or al,3 ; Enable Timer Channel 2 & Speaker data
out 61h,al ; program the 8255 with new setting-speaker on
sub cx,cx ; Sneaky way to put 0FFFFH into CX when
wait2: loop wait2 ; LOOP is first executed
mov al,ah ; Get original 8255 Port "PB" settings
out 61h,al ; Reset port to original values-speaker off
ret
blkbuf equ $ ;cluster buffer
fatbuf equ $+16384 ;FAT buffer.
code ends
end scavenge